package gc3d.gridspring;

import gc3d.griddata.GridData;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.gridgain.grid.GridException;
import org.gridgain.grid.GridJob;
import org.gridgain.grid.GridJobAdapter;
import org.gridgain.grid.GridJobResult;
import org.gridgain.grid.GridJobResultPolicy;
import org.gridgain.grid.gridify.GridifyArgument;
import org.gridgain.grid.gridify.GridifyTaskSplitAdapter;


/**
 * 
 * @author Pierrick
 * @see org.gridgain.grid.GridTask
 */
public class GridTaskSplit extends GridifyTaskSplitAdapter<Integer> {
	private static final long serialVersionUID = 1L;

	/**
	 * Split the rendering, clone our data structure specifying the frame number,
	 * then create the job-list, and execute each jobs (on nodes).
	 * @see org.gridgain.grid.GridTaskSplitAdapter#split(int, java.lang.Object)
	 */
	@Override
	protected Collection<? extends GridJob> split(int gridSize,
			GridifyArgument arg) throws GridException {
		GridPov gp = (GridPov)arg.getTarget();
		GridData gd = gp.getFile();
		System.out.println(this+".split gridSize="+gridSize);
		List<GridJobAdapter<GridData>> jobs = new ArrayList<GridJobAdapter<GridData>>(gd.getNumberOfFrames());
		// here we split from 0 to totalframes included
		for (int framenumber = 0, numberofframe = gd.getNumberOfFrames(); framenumber <= numberofframe; framenumber++) {
			GridData newGD = gd.cloneWithTaskNb(framenumber);
			jobs.add(new GridJobAdapter<GridData>(newGD) {
				private static final long serialVersionUID = 1L;

				//@Override
				public Serializable execute() throws GridException {
					GridPov gpov = new GridPovRender(getArgument());
					return gpov.render();
				}
			});
		}
		return jobs;
	}

	@Override
	public GridJobResultPolicy result(GridJobResult result,
			List<GridJobResult> received) throws GridException {
		if ((Integer) result.getData() != 0) {
			// restart job
			System.err.println("[ERROR] 1 job failed, reexecute it...");
			GridJobAdapter<GridData> job =  result.getJob();
			// TODO test this
			job.execute();
		}
		return super.result(result, received);
	}

	/**
	 * Collect the result of each nodes
	 * @return number (addition) of error(s), which should be 0
	 * @see org.gridgain.grid.GridTask#reduce(java.util.List)
	 */
	//@Override
	public Integer reduce(List<GridJobResult> results)
			throws GridException {
		System.out.println(this+".reduce");

		int result = 0;
		for (GridJobResult res : results) {
			result = result + new Integer((Integer) res.getData()).intValue();
		}

		return new Integer(result);
	}
}
